`timescale    1ps/1ps
module    v8_port_select_01(
    input  wire        resetb,
    input  wire        sclk,
    
    input  wire        flash_ms,
    input  wire        time_125ms,
    
    input  wire        gp0_rec_flag,
    input  wire [7:0]  gp0_rec_data,
    input  wire        gp0_rec_error,
    input  wire        gp0_blank_flag,
    
    input  wire        gp1_rec_flag,
    input  wire [7:0]  gp1_rec_data,
    input  wire        gp1_rec_error,
    input  wire        gp1_blank_flag,
            
    output reg         rec_flag,    //从包标志位('h0x81之后)开始有效
    output reg  [7:0]  rec_data,
    output reg         rec_error,    
    output reg  [1:0]  rec_vendor,    //在rec_flag有效时有效 0:无效包 1：UDP
    output reg         rec_error_sync,
    
    input  wire        send_flag,
    input  wire        pre_flag,
    input  wire [7:0]  send_data,

    output reg         blank_flag,
    output wire        redu_flag,
    
    output wire        gp0_send_flag,
    output wire        gp0_pre_flag,
    output wire [7:0]  gp0_send_data,
    
    output wire        gp1_send_flag,
    output wire        gp1_pre_flag,
    output wire [7:0]  gp1_send_data,
    
    output reg         input_active,

    output wire [7:0]  tout
    );
        
//******************************************************************/
//               信号定义
//******************************************************************/
reg  [2:0]  gp0_rec_temp,gp1_rec_temp;    //UDP
reg         gp0_vs_en_pre,gp0_active;
reg         gp1_vs_en_pre,gp1_active;
reg         gp1_input;
reg         gp0_rec_enout,gp1_rec_enout;
reg  [7:0]  gp0_rec_dout,gp1_rec_dout;
reg  [1:0]  flash_125ms_temp;
reg  [3:0]  gp0_no_vs_count,gp1_no_vs_count;    //UDP
reg  [2:0]  gp0_vs_count,gp1_vs_count;
wire        rec_error_a;     
reg  [2:0]  rec_error_shift;
reg  [7:0]  gp0_header_cnt,gp1_header_cnt;
reg         gp0_zdec_1,gp0_zdec_2,gp1_zdec_1,gp1_zdec_2;
reg         gp0_zdec_1_short,gp0_zdec_2_short,gp1_zdec_1_short,gp1_zdec_2_short;
wire        gp0_zdec_flag,gp1_zdec_flag;
reg  [3:0]  gp0_zdec_flag_t,gp1_zdec_flag_t;
reg  [1:0]  gp0_rec_vendor,gp1_rec_vendor;
reg         gp0_vs_valid,gp1_vs_valid;
reg         gp0_is_master,gp1_is_master;
reg         in_redu;

/************************************************/
//        A口检测
/************************************************/
//*********************帧包检测************************/
always @(posedge sclk)
    begin
    gp0_rec_temp<={gp0_rec_temp[1:0],gp0_rec_flag};    //UDP
    gp0_rec_dout<=gp0_rec_data;
    end

always @(posedge sclk)
    if(gp0_rec_flag==0)
        gp0_header_cnt<=0;
    else if(gp0_header_cnt[7]==0)
        gp0_header_cnt<=gp0_header_cnt+1'b1;

always @(posedge sclk)
    if(gp0_rec_flag==0)
        gp0_zdec_1<=0;
    else if(gp0_header_cnt==36 && gp0_rec_data==8'h55)
        gp0_zdec_1<=1'b1;

always @(posedge sclk)
    if(gp0_rec_flag==0)
        gp0_zdec_2<=0;
    else if(gp0_header_cnt==37 && gp0_rec_data==8'haa)
        gp0_zdec_2<=1'b1;        

always @(posedge sclk)
    if(gp0_rec_flag==0)
        gp0_zdec_1_short<=0;
    else if(gp0_header_cnt==(36-24) && gp0_rec_data==8'h55)
        gp0_zdec_1_short<=1'b1;

always @(posedge sclk)
    if(gp0_rec_flag==0)
        gp0_zdec_2_short<=0;
    else if(gp0_header_cnt==(37-24)&& gp0_rec_data==8'haa)
        gp0_zdec_2_short<=1'b1;        

assign gp0_zdec_flag=(gp0_zdec_1 & gp0_zdec_2) | (gp0_zdec_1_short & gp0_zdec_2_short);

always @(posedge sclk)
    gp0_zdec_flag_t<={gp0_zdec_flag_t[2:0],gp0_zdec_flag};
    
always @(posedge sclk)
    if(gp0_rec_flag==0)
        begin
        gp0_rec_vendor<=0;
        gp0_rec_enout<=0;
        end
    else if(gp0_zdec_flag_t[3]==1)    //为保证UDP包与长包包头数据能够对齐
        begin
        gp0_rec_vendor<=1'b1;
        gp0_rec_enout<=1'b1;
        end
    
always @(posedge sclk)
    if (gp0_rec_flag==0)
        gp0_vs_en_pre<=0;
    else if (gp0_header_cnt==43 && (gp0_rec_data==8'hFA || gp0_rec_data==8'hED) && (!(gp0_zdec_1_short & gp0_zdec_2_short)))    //UDP
        gp0_vs_en_pre<=1'b1;

always @(posedge sclk or negedge resetb)
    if (!resetb)
        gp0_is_master <= 1'b1;
    else if (gp0_header_cnt==46 && gp0_vs_en_pre)
        gp0_is_master <= ~gp0_rec_data[7];

always @(posedge sclk or negedge resetb)
    if (resetb==0)
        gp0_active<=0;
    else if (gp0_rec_temp[0]==1 && gp0_rec_flag==0 && gp0_vs_en_pre==1 && gp0_rec_error==0)
        gp0_active<=1'b1;
    else
        gp0_active<=0;

//*********************有帧包计时************************/
always @(posedge sclk or negedge resetb)
    if (resetb==0)
        gp0_vs_valid<=0;
    else if (gp0_vs_count>3)
        gp0_vs_valid<=1'b1;
    else
        gp0_vs_valid<=0;        

//*********************无帧包计时************************/
always @(posedge sclk)
    flash_125ms_temp<={flash_125ms_temp[0],time_125ms};
        
always @(posedge sclk or negedge resetb)
    if (resetb==0)
        gp0_no_vs_count<=0;
    else if (gp0_active==1)
        gp0_no_vs_count<=0;
    else if (((flash_125ms_temp[1:0]==2'b10) || (flash_125ms_temp[1:0]==2'b01)) && ( in_redu ? (gp0_no_vs_count[1] == 0): (gp0_no_vs_count[3]==0) ))    //UDP
        gp0_no_vs_count<=gp0_no_vs_count+1'b1;
        
/************************************************/
//        B口检测
/************************************************/
always @(posedge sclk)
    begin
    gp1_rec_temp<={gp1_rec_temp[1:0],gp1_rec_flag};    //UDP
    gp1_rec_dout<=gp1_rec_data;
    end

always @(posedge sclk)
    if(gp1_rec_flag==0)
        gp1_header_cnt<=0;
    else if(gp1_header_cnt[7]==0)
        gp1_header_cnt<=gp1_header_cnt+1'b1;

always @(posedge sclk)
    if(gp1_rec_flag==0)
        gp1_zdec_1<=0;
    else if(gp1_header_cnt==36 && gp1_rec_data==8'h55)
        gp1_zdec_1<=1'b1;

always @(posedge sclk)
    if(gp1_rec_flag==0)
        gp1_zdec_2<=0;
    else if(gp1_header_cnt==37 && gp1_rec_data==8'haa)
        gp1_zdec_2<=1'b1;        

always @(posedge sclk)
    if(gp1_rec_flag==0)
        gp1_zdec_1_short<=0;
    else if(gp1_header_cnt==(36-24) && gp1_rec_data==8'h55)
        gp1_zdec_1_short<=1'b1;

always @(posedge sclk)
    if(gp1_rec_flag==0)
        gp1_zdec_2_short<=0;
    else if(gp1_header_cnt==(37-24)&& gp1_rec_data==8'haa)
        gp1_zdec_2_short<=1'b1;        

assign gp1_zdec_flag=(gp1_zdec_1 & gp1_zdec_2) | (gp1_zdec_1_short & gp1_zdec_2_short);

always @(posedge sclk)
    gp1_zdec_flag_t<={gp1_zdec_flag_t[2:0],gp1_zdec_flag};

always @(posedge sclk)
    if(gp1_rec_flag==0)
        begin
        gp1_rec_vendor<=0;
        gp1_rec_enout<=0;
        end       
    else if(gp1_zdec_flag_t[3]==1)    //为保证UDP包与长包包头数据能够对齐
        begin     
        gp1_rec_vendor<=1'b1;
        gp1_rec_enout<=1'b1;
        end       
            
always @(posedge sclk)
    if (gp1_rec_flag==0)
        gp1_vs_en_pre<=0;
    else if (gp1_header_cnt==43 && (gp1_rec_data==8'hFA || gp1_rec_data==8'hED) && (!(gp1_zdec_1_short & gp1_zdec_2_short)))    //UDP
        gp1_vs_en_pre<=1'b1;
        
always @(posedge sclk or negedge resetb)
    if (!resetb)
        gp1_is_master <= 1'b1;
    else if (gp1_header_cnt==46 && gp1_vs_en_pre)
        gp1_is_master <= ~gp1_rec_data[7];

always @(posedge sclk or negedge resetb)
    if (resetb==0)
        gp1_active<=0;
    else if (gp1_rec_temp[0]==1 && gp1_rec_flag==0 && gp1_vs_en_pre==1 && gp1_rec_error==0)
        gp1_active<=1'b1;
    else
        gp1_active<=0;

//*********************有帧包计时************************/
always @(posedge sclk or negedge resetb)
    if (resetb==0)
        gp1_vs_valid<=0;
    else if (gp1_vs_count>3)
        gp1_vs_valid<=1'b1;
    else 
        gp1_vs_valid<=0;
                
//*********************无帧包计时************************/
always    @(posedge sclk or negedge resetb)
    if (resetb==0)
        gp1_no_vs_count<=0;
    else if (gp1_active==1)
        gp1_no_vs_count<=0;
    else if (((flash_125ms_temp[1:0]==2'b01) || (flash_125ms_temp[1:0]==2'b10))&& ( in_redu ? (gp1_no_vs_count[1] == 0): (gp1_no_vs_count[3]==0) ))        //UDP
        gp1_no_vs_count<=gp1_no_vs_count+1'b1;
                
/************************************************/
//        选择控制
/************************************************/
always@(posedge sclk or negedge resetb)
    if(resetb==0)
        gp1_input<=0;
    else if (redu_flag)
        begin
        if (gp0_is_master)
            gp1_input <= 1'b0;
        else if (gp1_is_master)
            gp1_input <= 1'b1;
        else
            gp1_input <= gp1_input;
        end
    else if(gp1_vs_valid==0 && gp0_vs_valid==0)
        gp1_input <= gp1_input;
    else if(gp1_vs_valid==1)
        gp1_input<=1'b1;
    else if(gp0_vs_valid==1)
        gp1_input<=0;

assign redu_flag=gp0_vs_valid && gp1_vs_valid;
/************************************************/
//        端口选择
/************************************************/
always @(posedge sclk)
    if(gp1_input==0) begin
        rec_flag<=gp0_rec_enout;
        rec_data<=gp0_rec_dout;                        
        rec_error<=gp0_rec_error;
        rec_vendor<=gp0_rec_vendor;
        blank_flag<=gp1_blank_flag;
    end
    else begin
        rec_flag<=gp1_rec_enout;
        rec_data<=gp1_rec_dout;                        
        rec_error<=gp1_rec_error;       
        rec_vendor<=gp1_rec_vendor;
        blank_flag<=gp0_blank_flag;  
    end 
                
assign gp0_send_flag=(gp1_input==0) ? send_flag : 1'b0;
assign gp0_pre_flag=(gp1_input==0)  ? pre_flag : 1'b0;
assign gp0_send_data=send_data;

assign gp1_send_flag=(gp1_input==0) ? 1'b0 : send_flag;
assign gp1_pre_flag=(gp1_input==0)  ? 1'b0 : pre_flag;
assign gp1_send_data=send_data;

assign rec_error_a=rec_error&rec_flag;
always @(posedge sclk)
    rec_error_shift<={rec_error_shift[1:0],rec_error_a};

always @(posedge sclk)
    if(rec_error_shift==2'b01)
        rec_error_sync<=1'b1;     
    else
        rec_error_sync<=1'b0;

/************************************************/
//        无信号输入
/************************************************/
always@(posedge sclk or negedge resetb)
    if(resetb==0)
        input_active<=0;
    else if (gp0_vs_count[2]||gp1_vs_count[2])
        input_active<=1'b1;
    else if ((in_redu ? (gp0_no_vs_count[1]==1) : (gp0_no_vs_count[3]==1)) && (in_redu ? (gp1_no_vs_count[1]==1) : (gp1_no_vs_count[3]==1)))    //UDP
        input_active<=0;

//******************************************************************/
//               测试输出
//******************************************************************/
always @(posedge sclk or negedge resetb)
    if (resetb==0)
        gp0_vs_count<=0;
    else if (gp0_active==1 && gp0_vs_count[2]==0)
        gp0_vs_count<=gp0_vs_count+1'b1;
    else if (in_redu ? (gp0_no_vs_count[1]==1) : (gp0_no_vs_count[3]==1))        //UDP
        gp0_vs_count<=0;

always    @(posedge sclk or negedge resetb)
    if (resetb==0)
        gp1_vs_count<=0;
    else if (gp1_active==1 && gp1_vs_count[2]==0)
        gp1_vs_count<=gp1_vs_count+1'b1;
    else if (in_redu ? (gp1_no_vs_count[1]==1) : (gp1_no_vs_count[3]==1))        //UDP
        gp1_vs_count<=0;
                
assign tout=0;

always @(posedge sclk)
    if ((!gp0_is_master && gp0_vs_valid) || (!gp1_is_master && gp1_vs_valid))
        in_redu <= 1'b1;
    else
        in_redu <= 1'b0;

endmodule

